#!/usr/bin/env python3
"""
RedFire项目清理脚本
==================
自动清理重复目录、空目录、无用文件

使用方法:
    python scripts/cleanup_project.py [backend_dir]

示例:
    python scripts/cleanup_project.py
    python scripts/cleanup_project.py /path/to/backend
"""

import os
import shutil
from pathlib import Path
from typing import List, Set
from datetime import datetime
import sys


class ProjectCleaner:
    """项目清理器"""
    
    def __init__(self, backend_dir: str):
        self.backend_dir = Path(backend_dir).resolve()
        self.removed_items: List[str] = []
        self.dry_run = False  # 是否为试运行模式
        
    def set_dry_run(self, dry_run: bool = True):
        """设置试运行模式"""
        self.dry_run = dry_run
        if dry_run:
            print("🔍 试运行模式 - 不会实际删除文件")
        
    def remove_duplicate_directories(self):
        """删除重复目录结构"""
        print("🔧 清理重复目录结构...")
        
        # user_service重复目录
        user_service_dir = self.backend_dir / "apps" / "user_service"
        duplicate_dirs = [
            "api", "core", "crud", "models", 
            "schemas", "services", "tests", "utils"
        ]
        
        for dir_name in duplicate_dirs:
            dir_path = user_service_dir / dir_name
            if dir_path.exists() and dir_path.is_dir():
                # 检查是否为空目录或只包含空的__init__.py
                if self._is_empty_or_init_only(dir_path):
                    if not self.dry_run:
                        shutil.rmtree(dir_path)
                    self.removed_items.append(str(dir_path))
                    print(f"  ✅ {'[试运行] ' if self.dry_run else ''}删除重复目录: {dir_path}")
                else:
                    print(f"  ⚠️ 跳过非空目录: {dir_path}")
    
    def remove_empty_directories(self):
        """删除空目录"""
        print("🗂️ 清理空目录...")
        
            # 多次遍历以处理嵌套空目录
        for _ in range(5):  # 最多5次迭代
            removed_in_iteration = []
            
            # 从底层开始遍历
            for root, dirs, files in os.walk(self.backend_dir, topdown=False):
                # 跳过虚拟环境目录
                if any(venv_name in root for venv_name in ['venv', '.venv', 'env', '.env', 'virtualenv']):
                    continue
                    
                for dir_name in dirs:
                    dir_path = Path(root) / dir_name
                    
                    # 跳过特殊目录
                    if dir_name in {'.git', '.vscode', '__pycache__', 'node_modules', 'venv', '.venv', 'env', '.env', 'virtualenv'}:
                        continue
                    
                    if dir_path.exists() and dir_path.is_dir():
                        if self._is_empty_or_init_only(dir_path):
                            try:
                                if not self.dry_run:
                                    if self._is_only_init_py(dir_path):
                                        # 如果只有__init__.py，先删除文件再删除目录
                                        (dir_path / "__init__.py").unlink()
                                    dir_path.rmdir()
                                self.removed_items.append(str(dir_path))
                                removed_in_iteration.append(str(dir_path))
                                print(f"  ✅ {'[试运行] ' if self.dry_run else ''}删除空目录: {dir_path}")
                            except OSError as e:
                                print(f"  ❌ 无法删除目录 {dir_path}: {e}")
            
            # 如果本轮没有删除任何目录，则退出循环
            if not removed_in_iteration:
                break
    
    def remove_deploy_directory(self):
        """删除deploy目录"""
        print("🚀 删除deploy目录...")
        
        deploy_dir = self.backend_dir / "deploy"
        if deploy_dir.exists():
            if not self.dry_run:
                shutil.rmtree(deploy_dir)
            self.removed_items.append(str(deploy_dir))
            print(f"  ✅ {'[试运行] ' if self.dry_run else ''}删除目录: {deploy_dir}")
        else:
            print("  ℹ️ deploy目录不存在，跳过")
    
    def remove_pycache_directories(self):
        """删除__pycache__目录（排除虚拟环境）"""
        print("🧹 清理__pycache__目录...")
        
        pycache_dirs = []
        for root, dirs, files in os.walk(self.backend_dir):
            # 跳过虚拟环境目录
            if any(venv_name in root for venv_name in ['venv', '.venv', 'env', '.env', 'virtualenv']):
                continue
            
            if "__pycache__" in dirs:
                pycache_dir = Path(root) / "__pycache__"
                pycache_dirs.append(pycache_dir)
        
        for pycache_dir in pycache_dirs:
            if not self.dry_run:
                shutil.rmtree(pycache_dir)
            self.removed_items.append(str(pycache_dir))
            print(f"  ✅ {'[试运行] ' if self.dry_run else ''}删除缓存目录: {pycache_dir}")
    
    def remove_log_files(self):
        """删除日志文件（可选）"""
        print("📝 清理日志文件...")
        
        log_patterns = ["*.log", "*.log.*"]
        log_files = []
        
        for pattern in log_patterns:
            log_files.extend(self.backend_dir.rglob(pattern))
        
        for log_file in log_files:
            if not self.dry_run:
                log_file.unlink()
            self.removed_items.append(str(log_file))
            print(f"  ✅ {'[试运行] ' if self.dry_run else ''}删除日志文件: {log_file}")
    
    def _is_empty_or_init_only(self, dir_path: Path) -> bool:
        """检查目录是否为空或只包含__init__.py"""
        try:
            contents = list(dir_path.iterdir())
            if not contents:
                return True  # 空目录
            
            # 只包含__init__.py且文件为空或只有注释
            if len(contents) == 1 and contents[0].name == "__init__.py":
                init_file = contents[0]
                if init_file.stat().st_size == 0:
                    return True  # 空的__init__.py
                
                # 检查是否只包含注释和空行
                try:
                    with open(init_file, 'r', encoding='utf-8') as f:
                        content = f.read().strip()
                        if not content or all(line.strip().startswith('#') or not line.strip() 
                                            for line in content.splitlines()):
                            return True
                except (UnicodeDecodeError, PermissionError):
                    pass
            
            return False
        except (PermissionError, OSError):
            return False
    
    def _is_only_init_py(self, dir_path: Path) -> bool:
        """检查目录是否只包含__init__.py"""
        try:
            contents = list(dir_path.iterdir())
            return len(contents) == 1 and contents[0].name == "__init__.py"
        except (PermissionError, OSError):
            return False
    
    def scan_project_structure(self):
        """扫描项目结构"""
        print("🔍 扫描项目结构...")
        
        apps_dir = self.backend_dir / "apps"
        if not apps_dir.exists():
            print(f"❌ apps目录不存在: {apps_dir}")
            return
        
        print(f"📁 项目根目录: {self.backend_dir}")
        print(f"📁 微服务目录: {apps_dir}")
        
        # 统计各种类型的目录和文件
        total_dirs = 0
        empty_dirs = 0
        services = []
        
        for item in apps_dir.iterdir():
            if item.is_dir():
                services.append(item.name)
                
                # 统计该服务的目录结构
                for root, dirs, files in os.walk(item):
                    total_dirs += len(dirs)
                    for dir_name in dirs:
                        dir_path = Path(root) / dir_name
                        if self._is_empty_or_init_only(dir_path):
                            empty_dirs += 1
        
        print(f"📊 统计信息:")
        print(f"  - 微服务数量: {len(services)}")
        print(f"  - 总目录数量: {total_dirs}")
        print(f"  - 空目录数量: {empty_dirs}")
        print(f"  - 微服务列表: {', '.join(services)}")
    
    def clean_all(self, include_logs: bool = False):
        """执行完整清理"""
        print("🎯 开始RedFire项目清理...")
        print("=" * 60)
        
        # 先扫描项目结构
        self.scan_project_structure()
        print("=" * 60)
        
        # 执行清理操作
        self.remove_duplicate_directories()
        self.remove_empty_directories() 
        self.remove_deploy_directory()
        self.remove_pycache_directories()
        
        if include_logs:
            self.remove_log_files()
        
        print("=" * 60)
        print(f"🎉 清理完成! 共{'计划' if self.dry_run else ''}删除 {len(self.removed_items)} 个项目")
        
        if self.removed_items:
            print(f"\n📋 {'计划' if self.dry_run else ''}删除清单:")
            for item in self.removed_items:
                print(f"  - {item}")
    
    def generate_report(self) -> str:
        """生成清理报告"""
        report = f"""# 🧹 RedFire项目清理报告

## 📊 清理统计
- **{'计划' if self.dry_run else ''}删除项目数**: {len(self.removed_items)}
- **清理时间**: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
- **运行模式**: {'试运行模式' if self.dry_run else '实际执行模式'}

## 📋 {'计划' if self.dry_run else ''}删除清单
"""
        
        if self.removed_items:
            for item in self.removed_items:
                report += f"- `{item}`\n"
        else:
            report += "无项目需要删除。\n"
        
        report += f"""
## 🎯 清理效果
- ✅ 消除重复目录结构
- ✅ 清理空目录和无用文件  
- ✅ 减少项目复杂度
- ✅ 提高代码可维护性

## 📝 后续建议
1. 建立标准化的微服务目录模板
2. 配置代码质量检查工具
3. 定期执行项目清理
4. 完善开发规范文档
"""
        return report


def main():
    """主函数"""
    import argparse
    
    parser = argparse.ArgumentParser(
        description="RedFire项目清理脚本",
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog="""
示例:
  python scripts/cleanup_project.py                    # 使用默认backend目录
  python scripts/cleanup_project.py /path/to/backend   # 指定backend目录
  python scripts/cleanup_project.py --dry-run          # 试运行模式
  python scripts/cleanup_project.py --include-logs     # 同时清理日志文件
        """
    )
    
    parser.add_argument(
        'backend_dir', 
        nargs='?', 
        default=None,
        help='backend目录路径 (默认: 脚本所在目录的上级目录)'
    )
    
    parser.add_argument(
        '--dry-run', 
        action='store_true',
        help='试运行模式，不实际删除文件'
    )
    
    parser.add_argument(
        '--include-logs', 
        action='store_true',
        help='同时清理日志文件'
    )
    
    parser.add_argument(
        '--report-only', 
        action='store_true',
        help='只生成报告，不执行清理'
    )
    
    args = parser.parse_args()
    
    # 确定backend目录
    if args.backend_dir:
        backend_dir = args.backend_dir
    else:
        # 默认为脚本所在目录的上级目录
        script_dir = Path(__file__).parent
        backend_dir = script_dir.parent
    
    # 验证目录
    backend_path = Path(backend_dir)
    if not backend_path.exists():
        print(f"❌ 错误: backend目录不存在: {backend_path}")
        sys.exit(1)
    
    if not (backend_path / "apps").exists():
        print(f"❌ 错误: 不是有效的RedFire backend目录 (缺少apps子目录): {backend_path}")
        sys.exit(1)
    
    # 创建清理器
    cleaner = ProjectCleaner(str(backend_path))
    
    # 设置模式
    if args.dry_run or args.report_only:
        cleaner.set_dry_run(True)
    
    # 执行清理
    if not args.report_only:
        cleaner.clean_all(include_logs=args.include_logs)
    else:
        cleaner.scan_project_structure()
    
    # 生成报告
    report = cleaner.generate_report()
    report_file = backend_path / "cleanup_report.md"
    
    try:
        with open(report_file, "w", encoding="utf-8") as f:
            f.write(report)
        print(f"\n📄 清理报告已保存到: {report_file}")
    except Exception as e:
        print(f"❌ 保存报告失败: {e}")
    
    # 如果是试运行，提示用户
    if args.dry_run:
        print(f"\n💡 这是试运行模式。要实际执行清理，请运行:")
        print(f"   python {__file__} {backend_dir}")
    elif args.report_only:
        print(f"\n💡 这是报告模式。要执行清理，请运行:")
        print(f"   python {__file__} {backend_dir}")


if __name__ == "__main__":
    main()
